//! 测试数据生成器
//! 
//! 提供各种类型的测试数据生成功能：
//! - Redis命令测试数据
//! - 集群配置测试数据  
//! - 性能测试数据
//! - 错误场景测试数据

use std::collections::HashMap;
use serde_json::Value;
use crate::common::generate_random_string;

/// Redis命令测试数据
#[derive(Debug, Clone)]
pub struct RedisCommandData {
    pub command: String,
    pub args: Vec<String>,
    pub expected_result: Option<String>,
}

/// 集群节点测试数据
#[derive(Debug, Clone)]
pub struct ClusterNodeData {
    pub node_id: String,
    pub host: String,
    pub port: u16,
    pub cluster_port: u16,
    pub role: NodeRole,
}

#[derive(Debug, Clone)]
pub enum NodeRole {
    Master,
    Slave,
}

/// 测试数据生成器
pub struct TestDataGenerator {
    seed: u64,
}

impl TestDataGenerator {
    /// 创建新的数据生成器
    pub fn new() -> Self {
        Self {
            seed: std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .unwrap()
                .as_nanos() as u64,
        }
    }
    
    /// 使用指定种子创建数据生成器（用于可重现的测试）
    pub fn with_seed(seed: u64) -> Self {
        Self { seed }
    }
    
    /// 生成基础Redis命令测试数据
    pub fn generate_basic_commands(&self) -> Vec<RedisCommandData> {
        vec![
            // PING命令
            RedisCommandData {
                command: "PING".to_string(),
                args: vec![],
                expected_result: Some("PONG".to_string()),
            },
            
            // SET/GET命令
            RedisCommandData {
                command: "SET".to_string(),
                args: vec!["test_key".to_string(), "test_value".to_string()],
                expected_result: Some("OK".to_string()),
            },
            RedisCommandData {
                command: "GET".to_string(),
                args: vec!["test_key".to_string()],
                expected_result: Some("test_value".to_string()),
            },
            
            // EXISTS命令
            RedisCommandData {
                command: "EXISTS".to_string(),
                args: vec!["test_key".to_string()],
                expected_result: Some("1".to_string()),
            },
            RedisCommandData {
                command: "EXISTS".to_string(),
                args: vec!["nonexistent_key".to_string()],
                expected_result: Some("0".to_string()),
            },
            
            // DEL命令
            RedisCommandData {
                command: "DEL".to_string(),
                args: vec!["test_key".to_string()],
                expected_result: Some("1".to_string()),
            },
            
            // INCR/INCRBY命令
            RedisCommandData {
                command: "SET".to_string(),
                args: vec!["counter".to_string(), "10".to_string()],
                expected_result: Some("OK".to_string()),
            },
            RedisCommandData {
                command: "INCR".to_string(),
                args: vec!["counter".to_string()],
                expected_result: Some("11".to_string()),
            },
            RedisCommandData {
                command: "INCRBY".to_string(),
                args: vec!["counter".to_string(), "5".to_string()],
                expected_result: Some("16".to_string()),
            },
            
            // TYPE命令
            RedisCommandData {
                command: "SET".to_string(),
                args: vec!["string_key".to_string(), "value".to_string()],
                expected_result: Some("OK".to_string()),
            },
            RedisCommandData {
                command: "TYPE".to_string(),
                args: vec!["string_key".to_string()],
                expected_result: Some("string".to_string()),
            },
        ]
    }
    
    /// 生成数字操作测试数据
    pub fn generate_numeric_commands(&self) -> Vec<RedisCommandData> {
        vec![
            RedisCommandData {
                command: "SET".to_string(),
                args: vec!["num1".to_string(), "0".to_string()],
                expected_result: Some("OK".to_string()),
            },
            RedisCommandData {
                command: "INCR".to_string(),
                args: vec!["num1".to_string()],
                expected_result: Some("1".to_string()),
            },
            RedisCommandData {
                command: "INCRBY".to_string(),
                args: vec!["num1".to_string(), "10".to_string()],
                expected_result: Some("11".to_string()),
            },
            RedisCommandData {
                command: "DECR".to_string(),
                args: vec!["num1".to_string()],
                expected_result: Some("10".to_string()),
            },
            RedisCommandData {
                command: "DECRBY".to_string(),
                args: vec!["num1".to_string(), "3".to_string()],
                expected_result: Some("7".to_string()),
            },
        ]
    }
    
    /// 生成错误场景测试数据
    pub fn generate_error_scenarios(&self) -> Vec<RedisCommandData> {
        vec![
            // 错误的命令
            RedisCommandData {
                command: "UNKNOWN_COMMAND".to_string(),
                args: vec![],
                expected_result: None, // 期望错误
            },
            
            // 参数不足
            RedisCommandData {
                command: "SET".to_string(),
                args: vec!["only_key".to_string()],
                expected_result: None, // 期望错误
            },
            
            // 参数过多
            RedisCommandData {
                command: "PING".to_string(),
                args: vec!["extra".to_string(), "args".to_string()],
                expected_result: None, // 期望错误
            },
            
            // 对非数字键执行数字操作
            RedisCommandData {
                command: "SET".to_string(),
                args: vec!["text_key".to_string(), "not_a_number".to_string()],
                expected_result: Some("OK".to_string()),
            },
            RedisCommandData {
                command: "INCR".to_string(),
                args: vec!["text_key".to_string()],
                expected_result: None, // 期望错误
            },
        ]
    }
    
    /// 生成大量测试数据（用于性能测试）
    pub fn generate_bulk_data(&self, count: usize) -> Vec<RedisCommandData> {
        let mut commands = Vec::with_capacity(count * 2);
        
        for i in 0..count {
            let key = format!("bulk_key_{}", i);
            let value = format!("bulk_value_{}", i);
            
            // SET命令
            commands.push(RedisCommandData {
                command: "SET".to_string(),
                args: vec![key.clone(), value.clone()],
                expected_result: Some("OK".to_string()),
            });
            
            // GET命令
            commands.push(RedisCommandData {
                command: "GET".to_string(),
                args: vec![key],
                expected_result: Some(value),
            });
        }
        
        commands
    }
    
    /// 生成随机键值对
    pub fn generate_random_kvp(&self, key_length: usize, value_length: usize) -> (String, String) {
        (
            generate_random_string(key_length),
            generate_random_string(value_length),
        )
    }
    
    /// 生成集群节点测试数据
    pub fn generate_cluster_nodes(&self, count: usize, start_port: u16) -> Vec<ClusterNodeData> {
        let mut nodes = Vec::with_capacity(count);
        
        for i in 0..count {
            let role = if i < count / 2 { NodeRole::Master } else { NodeRole::Slave };
            
            nodes.push(ClusterNodeData {
                node_id: format!("node_{}", i),
                host: "127.0.0.1".to_string(),
                port: start_port + i as u16,
                cluster_port: start_port + 10000 + i as u16,
                role,
            });
        }
        
        nodes
    }
    
    /// 生成配置测试数据
    pub fn generate_config_data(&self) -> HashMap<String, Value> {
        let mut config = HashMap::new();
        
        config.insert("host".to_string(), Value::String("127.0.0.1".to_string()));
        config.insert("port".to_string(), Value::Number(6379.into()));
        config.insert("timeout".to_string(), Value::Number(5000.into()));
        config.insert("max_connections".to_string(), Value::Number(100.into()));
        config.insert("enable_cluster".to_string(), Value::Bool(false));
        
        config
    }
    
    /// 生成压力测试场景数据
    pub fn generate_stress_scenarios(&self) -> Vec<StressTestScenario> {
        vec![
            StressTestScenario {
                name: "单线程顺序操作".to_string(),
                threads: 1,
                operations_per_thread: 1000,
                operation_type: OperationType::Mixed,
            },
            StressTestScenario {
                name: "多线程并发读取".to_string(),
                threads: 10,
                operations_per_thread: 100,
                operation_type: OperationType::Read,
            },
            StressTestScenario {
                name: "多线程并发写入".to_string(),
                threads: 5,
                operations_per_thread: 200,
                operation_type: OperationType::Write,
            },
            StressTestScenario {
                name: "高并发混合操作".to_string(),
                threads: 20,
                operations_per_thread: 50,
                operation_type: OperationType::Mixed,
            },
        ]
    }
}

impl Default for TestDataGenerator {
    fn default() -> Self {
        Self::new()
    }
}

/// 压力测试场景
#[derive(Debug, Clone)]
pub struct StressTestScenario {
    pub name: String,
    pub threads: usize,
    pub operations_per_thread: usize,
    pub operation_type: OperationType,
}

#[derive(Debug, Clone)]
pub enum OperationType {
    Read,
    Write,
    Mixed,
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_basic_commands_generation() {
        let generator = TestDataGenerator::new();
        let commands = generator.generate_basic_commands();
        
        assert!(!commands.is_empty());
        
        // 检查是否包含PING命令
        let ping_cmd = commands.iter().find(|cmd| cmd.command == "PING");
        assert!(ping_cmd.is_some());
        assert_eq!(ping_cmd.unwrap().expected_result, Some("PONG".to_string()));
    }
    
    #[test]
    fn test_numeric_commands_generation() {
        let generator = TestDataGenerator::new();
        let commands = generator.generate_numeric_commands();
        
        assert!(!commands.is_empty());
        
        // 检查是否包含INCR命令
        let incr_cmd = commands.iter().find(|cmd| cmd.command == "INCR");
        assert!(incr_cmd.is_some());
    }
    
    #[test]
    fn test_error_scenarios_generation() {
        let generator = TestDataGenerator::new();
        let scenarios = generator.generate_error_scenarios();
        
        assert!(!scenarios.is_empty());
        
        // 检查是否包含错误场景
        let error_cmd = scenarios.iter().find(|cmd| cmd.command == "UNKNOWN_COMMAND");
        assert!(error_cmd.is_some());
        assert!(error_cmd.unwrap().expected_result.is_none());
    }
    
    #[test]
    fn test_bulk_data_generation() {
        let generator = TestDataGenerator::new();
        let commands = generator.generate_bulk_data(10);
        
        assert_eq!(commands.len(), 20); // 10个SET + 10个GET
        
        // 检查命令类型分布
        let set_count = commands.iter().filter(|cmd| cmd.command == "SET").count();
        let get_count = commands.iter().filter(|cmd| cmd.command == "GET").count();
        assert_eq!(set_count, 10);
        assert_eq!(get_count, 10);
    }
    
    #[test]
    fn test_cluster_nodes_generation() {
        let generator = TestDataGenerator::new();
        let nodes = generator.generate_cluster_nodes(6, 7000);
        
        assert_eq!(nodes.len(), 6);
        
        // 检查端口分配
        assert_eq!(nodes[0].port, 7000);
        assert_eq!(nodes[1].port, 7001);
        assert_eq!(nodes[0].cluster_port, 17000);
        assert_eq!(nodes[1].cluster_port, 17001);
        
        // 检查角色分配（前半部分是Master）
        assert!(matches!(nodes[0].role, NodeRole::Master));
        assert!(matches!(nodes[1].role, NodeRole::Master));
        assert!(matches!(nodes[2].role, NodeRole::Master));
        assert!(matches!(nodes[3].role, NodeRole::Slave));
    }
    
    #[test]
    fn test_config_data_generation() {
        let generator = TestDataGenerator::new();
        let config = generator.generate_config_data();
        
        assert!(!config.is_empty());
        assert!(config.contains_key("host"));
        assert!(config.contains_key("port"));
        assert!(config.contains_key("timeout"));
    }
    
    #[test]
    fn test_stress_scenarios_generation() {
        let generator = TestDataGenerator::new();
        let scenarios = generator.generate_stress_scenarios();
        
        assert!(!scenarios.is_empty());
        
        // 检查不同类型的场景
        let single_thread = scenarios.iter().find(|s| s.threads == 1);
        assert!(single_thread.is_some());
        
        let multi_thread = scenarios.iter().find(|s| s.threads > 1);
        assert!(multi_thread.is_some());
    }
    
    #[test]
    fn test_random_kvp_generation() {
        let generator = TestDataGenerator::new();
        let (key1, value1) = generator.generate_random_kvp(10, 20);
        let (key2, value2) = generator.generate_random_kvp(10, 20);
        
        assert_eq!(key1.len(), 10);
        assert_eq!(value1.len(), 20);
        assert_ne!(key1, key2);
        assert_ne!(value1, value2);
    }
    
    #[test]
    fn test_generator_with_seed() {
        let generator1 = TestDataGenerator::with_seed(12345);
        let generator2 = TestDataGenerator::with_seed(12345);
        
        // 使用相同种子应该产生相同的结果
        let (key1, _) = generator1.generate_random_kvp(10, 10);
        let (key2, _) = generator2.generate_random_kvp(10, 10);
        
        // 注意：这里只是测试框架，实际的随机性可能需要更复杂的种子控制
        assert_eq!(generator1.seed, generator2.seed);
    }
}